﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Runtime.Serialization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
using XamlingCore.Infrastructure.Serialisation;
using XamlingCore.Infrastructure.View;
using XamlingCore.Infrastructure.View.Interface;
using XamlingCore.WP.Infrastructure.View.Interface;

namespace XamlingCore.Infrastructure.Navigation
{
    [DataContract]
    public class XNavigationService : NotifyBase
    {
        private bool isReverseNavigation;

        private List<object> navigationHistory;

        private object currentContentObject;
        private object previousObject;

        private bool canGoBack;

        public event EventHandler Navigated;

        private object serialiseContentOject;

        public XFrameViewModelBase ParentFrame { get; set; }

        public XNavigationService()
        {
            NavigationHistory = new List<object>();
        }

        public void InsertIntoHistory(object obj)
        {
            navigationHistory.Add(obj);
        }

        public void Serialise(IEnumerable<Type> knownTypes)
        {


        }

        public void Resume()
        {
            var contentModel = serialiseContentOject as XContentViewModelBase;
            if (contentModel != null)
            {
                contentModel.ParentModel =
                    ParentFrame.FindModel(contentModel.ParentModelGuid);
                contentModel.IsReady = true;
            }


            var resumeCurrent = serialiseContentOject as IReactivate;
            if (resumeCurrent != null)
            {
                resumeCurrent.OnReactivate();
            }
            
            if (CurrentContentObject == null)
            {
                CurrentContentObject = serialiseContentOject;    
            }
            
        }

        public void ResetHistory()
        {
            navigationHistory.Clear();
            CanGoBack = false;
        }

        public void NavigateTo(object content)
        {
            NavigateTo(content, false);
        }

        public void NavigateTo(object content, bool noHistory)
        {
            NavigateTo(content, noHistory, false);
        }

        public void NavigateTo(object content, bool noHistory, bool forceBack)
        {
            //var objChild = content as XContentViewModelBase;

            //if (objChild != null)
            //{
            //    objChild.OnBeforeActivate();
            //}

            //var objParent = content as XFrameViewModelBase;

            //if (objParent != null)
            //{
            //    objParent.OnBeforeActivate();
            //}

            if (content != null)
            {
                if (navigationHistory.Contains(content))
                {
                    IsReverseNavigation = true;
                    while (navigationHistory[navigationHistory.Count - 1] != content)
                    {
                        navigationHistory.Remove(navigationHistory[navigationHistory.Count - 1]);
                    }

                    navigationHistory.Remove(content);
                }
                else
                {
                    IsReverseNavigation = false;

                    if (!noHistory && CurrentContentObject != null)
                    {
                        navigationHistory.Add(CurrentContentObject);
                    }

                }

                CanGoBack = NavigationHistory.Count > 0;

                if (!noHistory)
                {
                    if (navigationHistory.Count > 0 && CurrentContentObject != null)
                    {
                        PreviousContentObject = CurrentContentObject;
                    }
                    else
                    {
                        PreviousContentObject = null;
                    }
                }

                if (forceBack)
                {
                    IsReverseNavigation = true;
                }

                CurrentContentObject = content;

                //tell a navigation item when it's view has been taken down
                if (NavigationHistory.Count > 1)
                {
                    var contentModel = navigationHistory[navigationHistory.Count - 2] as XContentViewModelBase;
                    if (contentModel != null)
                    {
                        contentModel.OnViewDeactivated();
                    }
                }
            }
            else
            {
                IsReverseNavigation = true;
                CurrentContentObject = null;
            }

            if (Navigated != null)
            {
                Navigated(this, EventArgs.Empty);
            }
        }

        public void NavigateBack()
        {
            NavigateBack(false);
        }

        public void NavigateBack(bool allowNullNavigation)
        {
            if (navigationHistory.Count > 1)
            {
                NavigateTo(navigationHistory[navigationHistory.Count - 1], false, true);
            }
            else if (navigationHistory.Count == 1)
            {
                NavigateTo(navigationHistory[0], true, true);
            }
            else if (allowNullNavigation)
            {
                NavigateTo(null, false, true);
            }
        }

        void setActive(bool isActive)
        {
            var active = currentContentObject as IActiveAware;

            if (active != null)
            {
                active.IsActive(isActive);
            }
        }

        public bool IsReverseNavigation
        {
            get { return isReverseNavigation; }
            set
            {
                isReverseNavigation = value;
                OnPropertyChanged("IsReverseNavigation");
            }
        }

        [DataMember]
        public List<object> NavigationHistory
        {
            get { return navigationHistory; }
            set
            {
                navigationHistory = value;
                OnPropertyChanged("NavigationHistory");
            }
        }

        public object CurrentContentObject
        {
            get { return currentContentObject; }
            set
            {

                setActive(false);
                currentContentObject = value;
                setActive(true);

                if (CurrentContentObject != null)
                {
                    SerialiseContentObject = value;
                }

                OnPropertyChanged("CurrentContentObject");
            }
        }

        [DataMember]//this is to ensure that current content object is not set until everything is ready
        public object SerialiseContentObject
        {
            get { return serialiseContentOject; }
            set { serialiseContentOject = value; }
        }

        [DataMember]
        public object PreviousContentObject
        {
            get { return previousObject; }
            set
            {
                previousObject = value;
                OnPropertyChanged("PreviousContentObject");
            }
        }

        [DataMember]
        public bool CanGoBack
        {
            get { return canGoBack; }
            set
            {
                canGoBack = value;
                OnPropertyChanged("CanGoBack");
            }
        }
    }


    public enum NavigationDirection
    {
        Forward,
        Back
    }
}
